package cn.wowjoy.pda.android_pharmacy.common.core.http;

import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

import java.io.IOException;
import java.lang.reflect.Field;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import cn.wowjoy.pda.android_pharmacy.common.utils.PreferenceManager;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.BufferedSink;
import okio.GzipSink;
import okio.Okio;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;

public class ServiceFactory<S> {

    private final static long DEFAULT_TIMEOUT = 10;//超时时间 10秒
    private Map<Class<S>, S> serviceMap;

    private static class SingletonHolder {
        private static final ServiceFactory INSTANCE = new ServiceFactory();
    }

    public static ServiceFactory getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public S getService(Class<S> serviceClass) {
        if (null == serviceMap) {
            serviceMap = new HashMap<>();
        }
        if (null != serviceMap.get(serviceClass)) {
            return serviceMap.get(serviceClass);
        }
        S service = createService(serviceClass);
        serviceMap.put(serviceClass, service);
        return service;
    }
    public S getServiceMerge(Class<S> serviceClass) {
        if (null == serviceMap) {
            serviceMap = new HashMap<>();
        }
        if (null != serviceMap.get(serviceClass)) {
            return serviceMap.get(serviceClass);
        }
        S service = createService(serviceClass,1);
        serviceMap.put(serviceClass, service);
        return service;
    }
    public S getServiceLogin(Class<S> serviceClass) {
        if (null == serviceMap) {
            serviceMap = new HashMap<>();
        }
        if (null != serviceMap.get(serviceClass)) {
            return serviceMap.get(serviceClass);
        }
        S service = createService(serviceClass,1);
        serviceMap.put(serviceClass, service);
        return service;
    }
    public S createService(Class<S> serviceClass) {
        String baseUrl = "";
        try {
            Field field = serviceClass.getField("BASE_URL");
            baseUrl = (String) field.get(serviceClass);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.getMessage();
            e.printStackTrace();
        }
        Retrofit retrofit;
        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(getOkHttpClient())
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        return retrofit.create(serviceClass);
    }
    public S createService(Class<S> serviceClass,int type) {
        String baseUrl = "";
        try {
            Field field = serviceClass.getField("BASE_URL");
            baseUrl = (String) field.get(serviceClass);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.getMessage();
            e.printStackTrace();
        }
        Retrofit retrofit;
        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(getOkHttpClientToken())
                .addConverterFactory(GsonConverterFactory.create(getGson()))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        return retrofit.create(serviceClass);
    }
    private Gson gson;
    private Gson getGson() {
        if (gson == null) {
            gson = new GsonBuilder().create();
        }
        return gson;
    }
    private OkHttpClient getOkHttpClientToken() {
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        //设置超时时间
        clientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        clientBuilder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        clientBuilder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
//        clientBuilder.retryOnConnectionFailure(false);

//        if (null == MyApplication.cookieJar)
//            MyApplication.cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(MyApplication.instance));
//        clientBuilder.cookieJar(MyApplication.cookieJar);

//        File cacheFile = new File(MyApplication.instance.getCacheDir(), "HttpCache"); // 指定缓存路径
//        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); // 指定缓存大小100Mb
//        clientBuilder.cache(cache);

//        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
//        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//        clientBuilder.addInterceptor(interceptor);

        Interceptor mTokenInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Request.Builder builder = request.newBuilder();
                builder.header("Content-Type", "application/json;charset=UTF-8");
                builder.addHeader("Connection", "close");
                if (TextUtils.isEmpty(request.header("Authorization"))) {
                    builder.addHeader("Authorization", "bearer " + PreferenceManager.getInstance().getCurrentUserAccessToken());
                }
                return chain.proceed(builder.build());
            }
        };
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);



//        clientBuilder.addNetworkInterceptor(mTokenInterceptor);
        clientBuilder.addInterceptor(mTokenInterceptor);
        return clientBuilder
                .addInterceptor(httpLoggingInterceptor)
                .build();
    }
    private OkHttpClient getOkHttpClient() {
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        //设置超时时间
        clientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        clientBuilder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        clientBuilder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        clientBuilder.retryOnConnectionFailure(false);

//        if (null == MyApplication.cookieJar)
//            MyApplication.cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(MyApplication.instance));
//        clientBuilder.cookieJar(MyApplication.cookieJar);

//        File cacheFile = new File(MyApplication.instance.getCacheDir(), "HttpCache"); // 指定缓存路径
//        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); // 指定缓存大小100Mb
//        clientBuilder.cache(cache);

//        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
//        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//        clientBuilder.addInterceptor(interceptor);

        Interceptor mTokenInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request originalRequest = chain.request();
                Log.e("Request", originalRequest.url().toString());
                Request authorised = originalRequest.newBuilder()
//                        .header("Content-Type", "text/xml;charset=UTF-8")//添加请求头
//                        .method(originalRequest.method(), originalRequest.body())
                        .build();
                return chain.proceed(authorised);
            }
        };
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);



        clientBuilder.addNetworkInterceptor(mTokenInterceptor);
        return clientBuilder
                .addInterceptor(httpLoggingInterceptor)
                .build();
    }

    //gzip压缩
    private RequestBody gzip(final RequestBody body) {
        return new RequestBody() {
            @Override
            public MediaType contentType() {
                return body.contentType();
            }

            @Override
            public long contentLength() {
                return -1; // 无法知道压缩后的数据大小
            }

            @Override
            public void writeTo(BufferedSink sink) throws IOException {
                BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
                body.writeTo(gzipSink);
                gzipSink.close();
            }
        };
    }

    //信任所有证书
    private static OkHttpClient.Builder getUnsafeOkHttpClient() {
        try {
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

//            OkHttpClient okHttpClient = builder.build();
            return builder;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
